#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <memory.h>

#include "sender.h"
#include "header.h"
#include "util.h"

int main(int argc, char const *argv[]) {
    printf("vc4FrameHead: %llu\t vc4FrameBody: %llu\nvc12FrameHead: %llu\t vc12FrameBody: %llu\n",
           sizeof(vc4FrameHead_t),sizeof(vc4FrameBody_t),sizeof (vc12FrameBody_t), sizeof(vc12FrameHead_t));

    // 生成一个数据块
    unsigned char buffer[8192];
    unsigned char *buffer_pt = (unsigned char *) &buffer;
    generatePersistBlock(FIXED, 8192, buffer_pt);
    for (int i = 0; i < 8192; ++i) {
        printf("%X",buffer_pt[i]);
    }
    printf("\n\n");

    printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");


    long vc4BlockCount = getVCBlockUsageFromBlockSize(VC_4,8192);
    printf("You needs %ld blocks.\n", vc4BlockCount);

    int16_t tempSQ = 3;
    int16_t numArray[tempSQ];
    getVCBlockNumToNumArrays(tempSQ,10,numArray);
    for (int i = 0; i < tempSQ; ++i) {
        printf("%d\n",numArray[i]);
    }

//    unsigned char splitOutBuffer[3][8193];
//    splitPersistDataToBodyFrame(VC_4,1,0,buffer_pt,8193,splitOutBuffer[0],splitOutBuffer[1],splitOutBuffer[2]);








    // 初始化

    // 参数解析 (读配置文件)
    // parameterPasser(argc, argv);

    // 数据分块

    // 打包

    // 输出

    //
    return 0;
}


bool generatePersistBlock(enum GENERATE_DATA_TYPE dataType, long dataSize, unsigned char *pload) {
    uint8_t pattern = {0};
    if (pload == NULL || dataSize <= 0) {
        // 处理无效的
        return false;
    }
    // 根据数据类型选择填充规律
    switch (dataType) {
        case FIXED:
            pattern = 0xF0; // 8位 填充规律为 10101010
            // 填充数据块
            for (long i = 0; i < dataSize; i++) {
                pload[i] = pattern;
            }
            break;
    }
#ifdef DEBUG
    printf("Data start:\n");
    for (long i = 0; i < dataSize; i++) {
        printf("%02X", pload[i]);
    }
    printf("\n");
    printf("Data END\n");
#endif /* ifdef DEBUG */
    return true;
}

//* @override 这个函数是一个重载函数!!
//bool generateDataFileFULL(enum VC_TYPE vcType, uint16_t logicalID, uint16_t physicalID, uint16_t SQ, uint16_t MFT,
//                          unsigned char *data) {
//}
//
//bool generateDataFile(enum VC_TYPE vcType, uint16_t MFT, uint16_t length, unsigned char *data) {
//}
//

#define MAX_FILE_SPLIT_PACKET_SIZE 1024 // 每个数据包的最大大小

//long splitFileIntoPackets(enum VC_TYPE vcType, int SQ, int startMFI, char *filename,) {
//    // 打开文件进行读取
//    FILE *file = fopen(filename, "rb");
//    if (file == NULL) {
//        printf("无法打开文件: %s\n", filename);
//        return false;
//    }
//
//    // 计算文件大小
//    fseek(file, 0, SEEK_END);
//    long fileSize = ftell(file);
//    fseek(file, 0, SEEK_SET);
//
//    // 计算数据包数量
//    switch (vcType) {
//        // TODO:
//        case VC_4:
//            break;
//    }
//    int packetCount = fileSize / MAX_FILE_SPLIT_PACKET_SIZE;
//    if (fileSize % MAX_FILE_SPLIT_PACKET_SIZE != 0) {
//        packetCount++;
//    }
//
//    // 创建数据包缓冲区
//    unsigned char packetBuffer[MAX_FILE_SPLIT_PACKET_SIZE];
//
//    // 逐个数据包进行读取和处理
//    for (int i = 0; i < packetCount; i++) {
//        // 读取数据块
//        size_t bytesRead = fread(packetBuffer, 1, MAX_FILE_SPLIT_PACKET_SIZE, file);
//
//#ifdef DEBUG
//        // 在这里可以对读取到的数据块进行处理
//        // 例如，可以将数据包发送到网络或存储到磁盘等等
//        // 这里仅简单示例，将数据包的内容打印出来
//        printf("数据包 #%d:\n", i);
//        for (size_t j = 0; j < bytesRead; j++) {
//            printf("%02X ", packetBuffer[j]);
//        }
//        printf("\n");
//#endif // DEBUG
//    }
//
//    // 关闭文件
//    fclose(file);
//    return true;
//}

/**
 * 给一个数据块的大小和传出方式, 返回这个块被加工后需要的空间.
 */
long getVCBlockUsageFromBlockSize(enum VC_TYPE vcType, long blockSize){
    long packetCount = 0;
    switch (vcType) {
        case VC_4:
            packetCount = blockSize / getVC4BodyLength();
            if (blockSize % getVC4BodyLength() != 0) {        // 如果有余数
                packetCount++;
            }
            return packetCount;
        case VC_12:
            packetCount = blockSize / getVC12BodyLength();
            if (blockSize % getVC12BodyLength() != 0) {        // 如果有余数
                packetCount++;
            }
            return packetCount;
    }
}



bool splitPersistDataToBodyFrame(enum VC_TYPE vcType, int16_t SQ, int16_t startMFI, const unsigned char* origin, long originLength, unsigned char* out, ...) {
    if (origin == NULL || out == NULL || SQ <= 0 || originLength <= 0) {
        return false; // 错误处理：输入参数无效
    }

    int blockSize;
    if (vcType == VC_4) {
        blockSize = getVC4BodyLength();
    } else if (vcType == VC_12) {
        blockSize = getVC12BodyLength();
    } else {
        return false; // 错误处理：未知的 VC_TYPE
    }


    va_list args;
    va_start(args, out);
    // 将 startMFI 插入到输出数组中
    for (int i = 0; i < SQ; i++) {
        out[i * blockSize] = startMFI;
    }

    printf("starting insert MFI:\n");


    // 拷贝 origin 中的每个字节顺序交替地插入到 SQ 个 out 数据块中
    for (long i = 0; i < originLength; i++) {
        for (int j = 0; j < SQ; j++) {
            out[j * blockSize + i + 1] = origin[i]; // 注意 +1 用于跳过 startMFI
        }
    }

    // 使用 va_arg 获取剩余的 SQ 个输出数组指针并填充数据块
    for (int i = 0; i < SQ; i++) {
        unsigned char* dest = va_arg(args, unsigned char*);
        if (dest == NULL) {
            va_end(args);
            return false; // 错误处理：输出数组为空指针
        }
        memcpy(dest, out + i * blockSize, blockSize);
    }

    va_end(args);
    return true;
}


void getVCBlockNumToNumArrays(int16_t SQ,int16_t blockNum, int16_t framesInLine[SQ]){
    if (SQ<=0||blockNum<=0|| framesInLine == NULL){
        return;
    }

    // 清空
    for (int i = 0; i < SQ; ++i) {
        framesInLine[i] = 0;
    }

    int16_t averageValue = (int16_t)(blockNum / SQ);
    int16_t remainingValue = (int16_t)(blockNum % SQ);

    // 先将每个元素填充为平均值
    for (int i = 0; i < SQ; i++) {
        framesInLine[i] = averageValue;
    }

    // 将剩余值依次填充到前面的元素中
    for (int i = 0; i < remainingValue; i++) {
        framesInLine[i]++;
    }
}